//
// Created by benxb on 2021/12/29.
//

#ifndef BENXDB_BENCH_TIMER_H
#define BENXDB_BENCH_TIMER_H

#include <chrono>
#include <common/logger.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

namespace benchmark {

class TimePair {
public:
    std::string info;
    std::chrono::duration<double> cost;
};

class Timer {
public:
    Timer() : duration_(std::chrono::steady_clock::duration::zero()) {}

    ~Timer() = default;

    void Start() {
        start_ = std::chrono::steady_clock::now();
    }

    void Resume() {
        start_ = std::chrono::steady_clock::now();
    }

    void Pause() {
        duration_ += std::chrono::steady_clock::now() - start_;
    }

    void Clear() {
        duration_ = std::chrono::steady_clock::duration::zero();
    }

    void StopAndPrint(const std::string& msg) {
        duration_ += std::chrono::steady_clock::now() - start_;
        std::cout << msg << ": " << duration_.count() << std::endl;
        duration_ = std::chrono::steady_clock::duration::zero();
    }

    void PauseAndPrint(const std::string& msg) {
        std::chrono::duration<double> diff = std::chrono::steady_clock::now() - start_;
        duration_ += diff;
    }

    void StopAndRecord(const std::string& msg) {
        duration_ += std::chrono::steady_clock::now() - start_;
        records_.push_back({.info = msg, .cost = duration_});
        duration_ = std::chrono::steady_clock::duration::zero();
    }

    void PrintAll() {
        for(const auto& r : records_) {
            std::cout << r.info << ": " << r.cost.count() << std::endl;
        }
    }

    void SaveRecords(const std::string& save_file) {
        std::fstream f(save_file, std::ios::trunc);
        for(const auto& r : records_) {
            f << r.info << ": " << r.cost.count() << std::endl;
        }
        f.close();
    }

private:
    std::chrono::time_point<std::chrono::steady_clock> start_;
    std::chrono::duration<double> duration_;
    std::vector<TimePair> records_{};
};

}

#endif //BENXDB_BENCH_TIMER_H
